Матч 322, Расстановка кораблей (BattleshipChecker)

Дивизион 2, Уровень 3

 

Рассмотрим игру в морской бой на поле 10*10. Начальное расположение должно иметь 1 четырехпалубный, 2 трехпалубных, 3 двухпалубных и 4 однопалубных корабля. Корабли должны располагаться параллельно сторонам игрового поля и не должны касаться друг друга.

Эффективностью расположения кораблей называется сумма количества строк и колонок, в которых нет ни одной ячейки корабля. По заданному расположению кораблей в массиве board вывести “REJECTED”, если оно не является допустимым. Иначе вывести эффективность их расположения.

 

Класс: BattleshipChecker

Метод: string checkBoard(vector<string> board)

Ограничения: board и каждый его элемент содержит 10 элементов, board[i][j] равно ‘.’ или ‘X’.

 

Вход. Массив board, содержащий начальное расположение кораблей.

 

Выход. Вывести “REJECTED”, если board содержит недопустимую расстановку кораблей. Иначе вывести сообщение “ACCEPTED, X POINTS”, где X равно эффективности расстановки кораблей.

 

Пример входа

board

{"......X...",

 ".XXX..X...",

 "......X...",

 "X.X...X...",

 "X.........",

 "...XX.X...",

 "......X...",

 ".XX...X...",

 "..........",

 ".X.X..X..."}

{"X.X.X.X...",

 "......X...",

 ".XX...X...",

 "......X...",

 "......X..X",

 "...X..X...",

 "...X..X...",

 "......X...",

 "..XX..X...",

 "......X..."}

{"X.......X.",

 "...XXXX...",

 ".X......X.",

 "....XX....",

 ".........X",

 ".........X",

 ".....XXX..",

 ".........X",

 "..X......X",

 "..X......X"}

 

Пример выхода

ACCEPTED, 5 POINTS

“REJECTED”

“ACCEPTED, 0 POINTS”

 

 

РЕШЕНИЕ

стратегия + поиск в глубину

 

Условие того, что корабли не касаются друг друга, эквивалентно тому, что не существует диагональных касаний. То есть ни для каких i, j (1 £ i, j £ 9) не должно выполняться board[i][j] = ‘X’ и board[i+1][j+1] = ‘X’ или board[i+1][j] = ‘X’ и board[i][j+1] = ‘X’.

Если не существует диагональных касаний, то все корабли имеют вертикальный или горизонтальный вид. При помощи функции поиска в глубину dfs вычисляем количество кораблей размера 1, 2, 3 и 4. Если существует корабль размера, большего 4, или существует иное количество кораблей, чем требуется в условии начального расположения, то выводим “REJECTED”.

Далее находим количество вертикалей и горизонталей, свободных от кораблей и выводим фразу “ACCEPTED” с соответствующим значением эффективности расстановки.

 

ПРОГРАММА

 

#include <cstdio>

#include <vector>

#include <string>

using namespace std;

 

int m[5] = {0,4,3,2,1};

vector<string> bd;

 

int dfs(int i,int j)

{

  if ((i < 0) || (i > 9) || (j < 0) || (j > 9)) return 0;

  if (bd[i][j] == '.') return 0;

  bd[i][j] = '.';

  return 1 + dfs(i-1,j) + dfs(i+1,j) + dfs(i,j-1) + dfs(i,j+1);

}

 

class BattleshipChecker

{

public:

  string checkBoard(vector<string> board)

  {

    string res="REJECTED";

    int i, j, c, row[10], col[10];

    char r[20];

    bd = board;

    for(i = 0; i < 9; i++) for(j = 0; j < 9; j++)

      if (((board[i][j] == 'X') && (board[i+1][j+1]  == 'X')) ||

          ((board[i+1][j]  == 'X') && (board[i][j+1] == 'X'))) return res;

    memset(row,0,sizeof(row));memset(col,0,sizeof(col));

    for(i = 0; i < 10; i++) for(j = 0; j < 10; j++)

      if (board[i][j] == 'X') row[i] = col[j] = 1;

    for(i = 0; i < 10; i++) for(j = 0; j < 10; j++)

      if (bd[i][j] == 'X')

      {

        c = dfs(i,j); if (c > 4) return res;

        m[c]--;

      }

    if (m[1] || m[2] || m[3] || m[4]) return res;

    for(c = 20 ,i = 0; i < 10; i++) c -= row[i] + col[i];

    sprintf(r,"ACCEPTED, %d POINTS",c); res = (string)r;

    return res;

  }

};